{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:17:49.224912Z",
     "start_time": "2019-11-04T02:17:48.156747Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bk-root\">\n",
       "        <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
       "        <span id=\"1001\">Loading BokehJS ...</span>\n",
       "    </div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null && id in Bokeh.index) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var id = msg.content.text.trim();\n",
       "            if (id in Bokeh.index) {\n",
       "              Bokeh.index[id].model.document.clear();\n",
       "              delete Bokeh.index[id];\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(\"1001\");\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
       "    }\n",
       "    finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.info(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(js_urls, callback) {\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = js_urls.length;\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var s = document.createElement('script');\n",
       "      s.src = url;\n",
       "      s.async = false;\n",
       "      s.onreadystatechange = s.onload = function() {\n",
       "        root._bokeh_is_loading--;\n",
       "        if (root._bokeh_is_loading === 0) {\n",
       "          console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
       "          run_callbacks()\n",
       "        }\n",
       "      };\n",
       "      s.onerror = function() {\n",
       "        console.warn(\"failed to load library \" + url);\n",
       "      };\n",
       "      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "    }\n",
       "  };var element = document.getElementById(\"1001\");\n",
       "  if (element == null) {\n",
       "    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n",
       "    return false;\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.0.0.min.js\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(js_urls, function() {\n",
       "      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(\"1001\");\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n    }\n    finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.info(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(js_urls, callback) {\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = js_urls.length;\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var s = document.createElement('script');\n      s.src = url;\n      s.async = false;\n      s.onreadystatechange = s.onload = function() {\n        root._bokeh_is_loading--;\n        if (root._bokeh_is_loading === 0) {\n          console.log(\"Bokeh: all BokehJS libraries loaded\");\n          run_callbacks()\n        }\n      };\n      s.onerror = function() {\n        console.warn(\"failed to load library \" + url);\n      };\n      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.getElementsByTagName(\"head\")[0].appendChild(s);\n    }\n  };var element = document.getElementById(\"1001\");\n  if (element == null) {\n    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n    return false;\n  }\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.0.0.min.js\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n    }\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(js_urls, function() {\n      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import torchvision.datasets as dsets\n",
    "import torchvision.transforms as transforms\n",
    "from torch.utils.data import DataLoader\n",
    "\n",
    "from bokeh.io import show, output_notebook\n",
    "from bokeh.plotting import figure, gridplot\n",
    "from bokeh.models import LinearAxis, Range1d\n",
    "output_notebook()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GPU\n",
    "指定使用的 GPU 编号。  \n",
    "`watch -n 1 nvidia-smi` 实时查看 GPU 的运行状态。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:17:49.367155Z",
     "start_time": "2019-11-04T02:17:49.229184Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.cuda.set_device(\"cuda:5\")\n",
    "torch.cuda.current_device()\n",
    "# device = torch.device(\"cuda:5\")\n",
    "# xxx.to(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-02T15:34:18.036850Z",
     "start_time": "2019-11-02T15:34:18.032937Z"
    }
   },
   "source": [
    "### Data\n",
    "通过`torchvision.datasets`下载`MNIST`数据。  \n",
    "训练集：`train=True`  \n",
    "测试集：`train=False`  \n",
    "常用的还有`torchvision.datasets.ImageFolder()`，按文件夹取图片。  \n",
    "\n",
    "`torchvision.transforms`可以对图片做处理。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:17:49.530670Z",
     "start_time": "2019-11-04T02:17:49.370242Z"
    }
   },
   "outputs": [],
   "source": [
    "train_dataset = dsets.MNIST(root='../dataset', train=True, transform=transforms.ToTensor(), download=True)\n",
    "test_dataset = dsets.MNIST(root='../dataset', train=False, transform=transforms.ToTensor(), download=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:17:49.561477Z",
     "start_time": "2019-11-04T02:17:49.534001Z"
    }
   },
   "outputs": [],
   "source": [
    "batch_size = 50\n",
    "train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)\n",
    "test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model\n",
    "构造前馈神经网络"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:17:49.728567Z",
     "start_time": "2019-11-04T02:17:49.564044Z"
    }
   },
   "outputs": [],
   "source": [
    "class FNN(nn.Module):\n",
    "    def __init__(self, dim_in, dim_hidden, dim_out):\n",
    "        super().__init__()\n",
    "        self.fc1 = nn.Linear(dim_in, dim_hidden)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(dim_hidden, dim_out)\n",
    "    def forward(self, x):\n",
    "        return self.fc2(self.relu(self.fc1(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:17:56.014974Z",
     "start_time": "2019-11-04T02:17:49.730983Z"
    }
   },
   "outputs": [],
   "source": [
    "dim_in = 28*28\n",
    "dim_hidden = 500\n",
    "dim_out = 10\n",
    "lrate = 0.001\n",
    "epochs = 40\n",
    "\n",
    "model = FNN(dim_in, dim_hidden, dim_out).double().cuda()\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optim = torch.optim.SGD(model.parameters(), lr=lrate)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意：每次反向传播的时候都需要将参数的梯度归零。  \n",
    "`optim.step()`则在每个`Variable`的`grad`都被计算出来后，更新每个`Variable`的数值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在每次训练中都用`train_loader`中的一个`batch`作为训练数据。  \n",
    "`Tensor.cuda()` 每个 `batch` 在实际使用之前，都先移入 `GPU` 后进行计算。  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:24:29.171159Z",
     "start_time": "2019-11-04T02:17:56.019188Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "  <div class=\"bk-root\" id=\"991d2e2b-916d-4e30-bf2d-2a699ace5992\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"ecaa8d43-9a41-417e-9555-29ac1c973ba7\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1011\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"1016\",\"type\":\"LinearAxis\"}],\"renderers\":[{\"id\":\"1011\",\"type\":\"LinearAxis\"},{\"id\":\"1015\",\"type\":\"Grid\"},{\"id\":\"1016\",\"type\":\"LinearAxis\"},{\"id\":\"1020\",\"type\":\"Grid\"},{\"id\":\"1029\",\"type\":\"BoxAnnotation\"},{\"id\":\"1039\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"1041\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"1027\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"1003\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"1007\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"1005\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"1009\",\"type\":\"LinearScale\"}},\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"line_color\":\"#1f77b4\",\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1037\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1021\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"overlay\":{\"id\":\"1029\",\"type\":\"BoxAnnotation\"}},\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"attributes\":{},\"id\":\"1024\",\"type\":\"SaveTool\"},{\"attributes\":{\"callback\":null},\"id\":\"1005\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1025\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"1026\",\"type\":\"HelpTool\"},{\"attributes\":{},\"id\":\"1007\",\"type\":\"LinearScale\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1021\",\"type\":\"PanTool\"},{\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"id\":\"1024\",\"type\":\"SaveTool\"},{\"id\":\"1025\",\"type\":\"ResetTool\"},{\"id\":\"1026\",\"type\":\"HelpTool\"}]},\"id\":\"1027\",\"type\":\"Toolbar\"},{\"attributes\":{\"plot\":null,\"text\":\"\"},\"id\":\"1041\",\"type\":\"Title\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1038\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LinearScale\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"value\":\"lightgrey\"},\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":{\"value\":1.0},\"line_color\":{\"value\":\"black\"},\"line_dash\":[4,4],\"line_width\":{\"value\":2},\"plot\":null,\"render_mode\":\"css\",\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"1029\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"callback\":null,\"data\":{\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],\"y\":[2.0073313034730647,1.6094349602776494,1.3680813346684233,1.0101019968697489,0.8924781789470321,0.6083467001621778,0.6545920092691653,0.4019273478465008,0.596468310482844,0.5952021827470613,0.5771858769360808,0.4724292451129979,0.550492270845578,0.47942151052288545,0.4173565810102234,0.3985889708172834,0.4199144873737913,0.31612026870481913,0.2833922074129706,0.3189870144183645,0.5519107942003936,0.2664527066005975,0.38102762066776225,0.3020305676846683,0.2996466808104683,0.34058562199639886,0.338785893649761,0.24461596805639083,0.2807555592926984,0.2797465089149127,0.20454850930751362,0.4396179095065518,0.5522674310797995,0.19684892161758327,0.3108363439810584,0.2544325665533972,0.4640755381295496,0.42790988254218504,0.26507627077950635,0.32583448628491823]},\"selected\":{\"id\":\"1048\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"1047\",\"type\":\"UnionRenderers\"}},\"id\":\"1036\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data_source\":{\"id\":\"1036\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"1037\",\"type\":\"Line\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1038\",\"type\":\"Line\"},\"selection_glyph\":null,\"view\":{\"id\":\"1040\",\"type\":\"CDSView\"}},\"id\":\"1039\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"formatter\":{\"id\":\"1044\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1012\",\"type\":\"BasicTicker\"}},\"id\":\"1011\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"1036\",\"type\":\"ColumnDataSource\"}},\"id\":\"1040\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1012\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1044\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1012\",\"type\":\"BasicTicker\"}},\"id\":\"1015\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1046\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"formatter\":{\"id\":\"1046\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1017\",\"type\":\"BasicTicker\"}},\"id\":\"1016\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1047\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"callback\":null},\"id\":\"1003\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1017\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1048\",\"type\":\"Selection\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1017\",\"type\":\"BasicTicker\"}},\"id\":\"1020\",\"type\":\"Grid\"}],\"root_ids\":[\"1002\"]},\"title\":\"Bokeh Application\",\"version\":\"1.0.0\"}};\n",
       "  var render_items = [{\"docid\":\"ecaa8d43-9a41-417e-9555-29ac1c973ba7\",\"roots\":{\"1002\":\"991d2e2b-916d-4e30-bf2d-2a699ace5992\"}}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "1002"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = []\n",
    "for e in range(epochs):\n",
    "    for i, (inputs, targets) in enumerate(train_loader):\n",
    "        inputs = inputs.reshape(-1, 28*28).double().cuda()\n",
    "        targets = targets.cuda()\n",
    "        optim.zero_grad()\n",
    "        outputs = model(inputs)\n",
    "        loss = criterion(outputs, targets)\n",
    "        loss.backward()\n",
    "        optim.step()\n",
    "    result.append(float(loss))\n",
    "    \n",
    "fig = figure()\n",
    "fig.line(range(len(result)), result)\n",
    "show(fig)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Result\n",
    "与 CPU 训练的情况对比，GPU 的迭代次数从 20 增加到 40，但时间从  8m 33s 减少到 6m 33s，且在训练过程中对 CPU 的占用明显减少。  \n",
    "由于迭代次数增加，准确率也从 90.20 % 增加到 91.74 %"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`re = torch.max(Tensor,dim)`, 返回的re为一个二维向量，其中`re[0]`为最大值的`Tensor`，re[1]为最大值对应的`index`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:24:35.249290Z",
     "start_time": "2019-11-04T02:24:29.173635Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of the model on the 10000 test images: 91.74 %\n"
     ]
    }
   ],
   "source": [
    "correct = 0\n",
    "total = 0\n",
    "wrong_count = 0\n",
    "wrong_classify = []\n",
    "for i, (inputs, targets) in enumerate(test_loader):\n",
    "    targets = targets.cuda()\n",
    "    inputs = inputs.reshape(-1, 28*28).double().cuda()\n",
    "    outputs = model(inputs)\n",
    "    _, preds = torch.max(outputs.data, 1)\n",
    "    total += len(outputs)\n",
    "    correct += (preds == targets).sum()\n",
    "    if wrong_count < 5 and preds != targets:\n",
    "        wrong_classify.append([inputs.data, preds, targets])\n",
    "        wrong_count += 1\n",
    "accuracy = 100 * correct.double() / total\n",
    "print('Accuracy of the model on the 10000 test images: %.2f %%' % (accuracy))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:24:36.217884Z",
     "start_time": "2019-11-04T02:24:35.251584Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x5400 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(15, wrong_count*15))\n",
    "for i, (img, preds, truth) in enumerate(wrong_classify):\n",
    "    img = img.reshape(28, 28).cpu().numpy()\n",
    "    plt.subplot(1, wrong_count, i+1)\n",
    "    plt.imshow(img)\n",
    "    plt.title('true:%i, pred:%i' % (truth, preds))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T07:12:44.915877Z",
     "start_time": "2019-11-03T07:12:44.913744Z"
    }
   },
   "source": [
    "### Save Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-04T02:24:36.272314Z",
     "start_time": "2019-11-04T02:24:36.220374Z"
    }
   },
   "outputs": [],
   "source": [
    "torch.save(model.state_dict(), 'feedfoward_nn_cuda.pkl')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "oldHeight": 511.99678000000006,
   "position": {
    "height": "533.984px",
    "left": "411.875px",
    "right": "20px",
    "top": "161.984px",
    "width": "760.516px"
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "varInspector_section_display": "block",
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
